/*
 *   The contents of this file are subject to the Mozilla Public License
 *   Version 1.1 (the "License"); you may not use this file except in
 *   compliance with the License. You may obtain a copy of the License at
 *   http://www.mozilla.org/MPL/
 *
 *   Software distributed under the License is distributed on an "AS IS"
 *   basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 *   License for the specific language governing rights and limitations
 *   under the License.
 *
 *   The Original Code is Matra - the DTD Parser.
 *
 *   The Initial Developer of the Original Code is Conrad S Roche.
 *   Portions created by Conrad S Roche are Copyright (C) Conrad 
 *   S Roche. All Rights Reserved.
 *
 *   Alternatively, the contents of this file may be used under the terms
 *   of the GNU GENERAL PUBLIC LICENSE Version 2 or any later version
 *   (the  "[GPL] License"), in which case the
 *   provisions of GPL License are applicable instead of those
 *   above.  If you wish to allow use of your version of this file only
 *   under the terms of the GPL License and not to allow others to use
 *   your version of this file under the MPL, indicate your decision by
 *   deleting  the provisions above and replace  them with the notice and
 *   other provisions required by the GPL License.  If you do not delete
 *   the provisions above, a recipient may use your version of this file
 *   under either the MPL or the GPL License."
 *
 *   [NOTE: The text of this Exhibit A may differ slightly from the text of
 *   the notices in the Source Code files of the Original Code. You should
 *   use the text of this Exhibit A rather than the text found in the
 *   Original Code Source Code for Your Modifications.]
 *
 * Created: Conrad S Roche <derupe at users.sourceforge.net>,  25-Jul-2000
 */

package com.conradroche.matra.decl;

import java.util.*;

import com.conradroche.matra.data.*;
import com.conradroche.matra.exception.*;

/**
 * Class to hold an entity declaration.
 *
 * @author Conrad Roche
 */
public class Entity implements com.conradroche.dtd.decl.Entity {

	private String name;
	private int type;

	/**
	 * Constant to indicate that this is a
	 * parameter entity.
	 */
	public static final int PARAMETER_ENTITY = 0;

	/**
	 * Constant to indicate that this is a
	 * global entity.
	 */
	public static final int GLOBAL_ENTITY = 1;

	/**
	 * Constant to indicate that this attribute
	 * has no external id.
	 */
	public static final int EXT_ID_NONE = 0;

	/**
	 * Constant to indicate that this attribute
	 * has a system id.
	 */
	public static final int EXT_ID_SYSTEM = 1;

	/**
	 * Constant to indicate that this attribute
	 * has a public id.
	 */
	public static final int EXT_ID_PUBLIC = 2;
	
	private String literalValue;

	private boolean hasEntityRef = false;
	private boolean resolved;
	private int externalIDType;
	private java.lang.String systemLiteral;
	private java.lang.String pubidLiteral;

/**
 * Entity constructor.
 */
public Entity() {
	super();
}

/**
 * Entity constructor.
 * 
 * @param name   The name of the entity.
 * @param value  The value of the enetity.
 * @param type   an int specifying the entity type. 
 */
public Entity(String name, String value, int type) {
	this.name = name;
	this.literalValue = value;
	this.type = type;
}

/**
 * Entity Constructor.
 * 
 * @param content The entity declaration.
 * 
 * @throws DTDException If any syntax error is encountered.
 */
public Entity(String content) throws DTDException {

/*
[70] EntityDecl ::= GEDecl | PEDecl
[71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
[72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
[73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
[74] PEDef ::= EntityValue | ExternalID

[9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' | "'" ([^%&'] | PEReference | Reference)* "'"
[75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral
[76] NDataDecl ::= S 'NDATA' S Name

[11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
[12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
[13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
*/
	DTDData entDecl = new DTDData(content);
		
	entDecl.skipWhiteSpace(); //S
	if(entDecl.checkNextChar('%') == Data.FOUND_CHAR) { //parameter entity
		setType(Entity.PARAMETER_ENTITY);
		
//		entDecl.getNextChar(); //'%'
		entDecl.skipWhiteSpace(); //S
		setEntityName( entDecl.getNextToken() ); //Name
		entDecl.skipWhiteSpace(); //S

		//PEDef
		String paramDef = readEntityValue(entDecl); //EntityValue

		if(paramDef == null) { //ExternalID
			String extID = readExtID(entDecl);
		}
		else {
			setLiteralValue(paramDef);
		}
		
		entDecl.skipWhiteSpace(); //S?
		//if(entDecl.getNextChar() != '>') //'>'
			//throw new DTDException("Invalid character (" + entDecl.getPrevChar() + ") encountered at location " + entDecl.getCurrentPosition() + " - was expecting '>'.");
	}
	else { //global entity
		setType(Entity.GLOBAL_ENTITY);
		setEntityName( entDecl.getNextToken() ); //Name
		entDecl.skipWhiteSpace(); //S
		
		//EntityDef
		String entityValue = readEntityValue(entDecl); //EntityValue
		if( entityValue == null) {
			String extID = readExtID(entDecl); //ExternalID
			//NDataDecl?
			entDecl.skipWhiteSpace(); //S
			char[] ndataDelim = {'>'};
			DTDData NDataDecl = new DTDData(entDecl.getNextToken(ndataDelim));
			if( NDataDecl.getNextToken().equals("NDATA") ) {
				NDataDecl.skipWhiteSpace(); //S
				String nData = NDataDecl.getNextToken(); //Name
			}
		}
		else
			setLiteralValue(entityValue);
	}

}
/**
 * Entity Constructor.
 * 
 * @param content The entity declaration.
 * @param EntityList  a Hashtable object
 * 
 * @throws DTDException If any syntax error is encountered.
 */
public Entity(String content, Hashtable EntityList) throws DTDException {

/*
[70] EntityDecl ::= GEDecl | PEDecl
[71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
[72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
[73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
[74] PEDef ::= EntityValue | ExternalID

[9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' | "'" ([^%&'] | PEReference | Reference)* "'"
[75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral
[76] NDataDecl ::= S 'NDATA' S Name

[11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
[12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
[13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
*/
	DTDData entDecl = new DTDData(content);
		
	entDecl.skipWhiteSpace(); //S
	if(entDecl.checkNextChar('%') == Data.FOUND_CHAR) { //parameter entity
		setType(Entity.PARAMETER_ENTITY);
		
//		entDecl.getNextChar(); //'%'
		entDecl.skipWhiteSpace(); //S
		setEntityName( entDecl.getNextToken() ); //Name
		entDecl.skipWhiteSpace(); //S

		//PEDef
		String paramDef = readEntityValue(entDecl); //EntityValue

		if(paramDef == null) { //ExternalID
			String extID = readExtID(entDecl);
		}
		else {
			paramDef = resolveEntities(new DTDData(paramDef), EntityList).toString();
			setLiteralValue(paramDef);
		}
		
		entDecl.skipWhiteSpace(); //S?
		//if(entDecl.getNextChar() != '>') //'>'
			//throw new DTDException("Invalid character (" + entDecl.getPrevChar() + ") encountered at location " + entDecl.getCurrentPosition() + " - was expecting '>'.");
	}
	else { //global entity
		setType(Entity.GLOBAL_ENTITY);
		setEntityName( entDecl.getNextToken() ); //Name
		entDecl.skipWhiteSpace(); //S
		
		//EntityDef
		String entityValue = readEntityValue(entDecl); //EntityValue
		if( entityValue == null) {
			String extID = readExtID(entDecl); //ExternalID
			//NDataDecl?
			entDecl.skipWhiteSpace(); //S
			char[] ndataDelim = {'>'};
			DTDData NDataDecl = new DTDData(entDecl.getNextToken(ndataDelim));
			if( NDataDecl.getNextToken().equals("NDATA") ) {
				NDataDecl.skipWhiteSpace(); //S
				String nData = NDataDecl.getNextToken(); //Name
			}
		}
		else
			setLiteralValue(entityValue);
	}

}
/**
 * Returns the external ID type for this entity.
 * 
 * @see #setExternalIDType
 * 
 * @return the external ID type for this entity.
 */
public int getExternalIDType() {
	return externalIDType;
}
/**
 * Returns the Entity Name.
 * 
 * @return The Entity Name.
 * 
 * @see #setEntityName
 */
public java.lang.String getEntityName() {
	return name;
}
/**
 * Returns the public identifier for this entity.
 * 
 * @return The public identifier for this entity.
 * 
 * @see #setPublicIdentifier
 */
public java.lang.String getPublicIdentifier() {
	return pubidLiteral;
}

/**
 * Sets the Public Identifier.
 * 
 * @param publicId The Public Identifier
 * 
 * @see #getPublicIdentifier
 */
public void setPublicIdentifier(String publicId) {
	pubidLiteral = publicId;
}

/**
 * Returns the resolved value for this entity.
 * 
 * @param EntityList  All the declared entities in this DTD.
 * 
 * @return The resolved value.
 */
public String getResolvedValue(Hashtable EntityList) {
	return resolveEntities(new DTDData(literalValue), EntityList).toString();
}
/**
 * Returns the system identifier.
 * 
 * @return The system identifier.
 * 
 * @see #setSystemIdentifier
 */
public java.lang.String getSystemIdentifier() {
	return systemLiteral;
}

/**
 * Sets the System Identifier.
 * 
 * @param systemId The System Identifier
 * 
 * @see #getSystemIdentifier
 */
public void setSystemIdentifier(String systemId) {
	systemLiteral = systemId;
}

/**
 * Returns the entity type.
 * 
 * @return The entity type.
 * 
 * @see #setType
 */
public int getType() {
	return type;
}
/**
 * Returns the literal value of this entity.
 * 
 * @return The literal value
 * 
 * @see #setLiteralValue
 */
public String getLiteralValue() {
	return literalValue;
}

/**
 * Returns the replacement text for this Entity.
 * 
 * From the XML 1.0 Specification - 
 * [Definition: The replacement text is the 
 * content of the entity, after replacement 
 * of character references and parameter-entity 
 * references.]
 * 
 * @return The replacement text.
 */
public String getReplacementText() {
	//CR: TODO: Implement this method
	return null;
}

/**
 * Returns <code>true</code> if this entity is an
 * internal entity; <code>false</code> otherwise.
 * 
 * From the XML 1.0 Specifications - 
 * [Definition: If the entity definition is an 
 * EntityValue, the defined entity is called an 
 * internal entity. There is no separate physical 
 * storage object, and the content of the entity 
 * is given in the declaration.] Note that some 
 * processing of entity and character references in 
 * the literal entity literalValue may be required to 
 * produce the correct replacement text
 * 
 * @return <code>true</code> if this entity is an
 * 		internal entity; <code>false</code> otherwise.
 */
public boolean isInternalEntity() {
	//CR: TODO: Implement this
	throw new Error("Not Implemented");
}

/**
 * Returns <code>true</code> if this entity is an
 * external entity; <code>false</code> otherwise.
 * 
 * Add javadoc for Entity::isExternalEntity
 * From the XML 1.0 Specifications -
 * Definition: If the entity is not internal, 
 * it is an external entity
 * 
 * @return <code>true</code> if this entity is an
 * 		external entity; <code>false</code> otherwise.
 */
public boolean isExternalEntity() {
	//CR: TODO: Implement this
	throw new Error("Not Implemented");
}


/**
 * Returns <code>true</code> if this entity is an
 * parsed entity; <code>false</code> otherwise.
 * 
 * From XML 1.0 Specifications -
 * [Definition: A parsed entity's contents are 
 * referred to as its replacement text; this text 
 * is considered an integral part of the document.]
 * 
 * @return <code>true</code> if this entity is an
 * 		parsed entity; <code>false</code> otherwise.
 */
public boolean isParsedEntity() {
	//CR: TODO: Implement this
	throw new Error("Not Implemented");
}

/**
 * Returns <code>true</code> if this entity is an
 * parsed entity; <code>false</code> otherwise.
 * 
 * From XML 1.0 Specifications -
 * [Definition: An unparsed entity is a resource 
 * whose contents may or may not be text, and if 
 * text, may be other than XML. Each unparsed 
 * entity has an associated notation, identified 
 * by name. Beyond a requirement that an XML 
 * processor make the identifiers for the entity 
 * and notation available to the application, 
 * XML places no constraints on the contents of 
 * unparsed entities.]
 * 
 * @return <code>true</code> if this entity is an
 * 		parsed entity; <code>false</code> otherwise.
 */
public boolean isUnparsedEntity() {
	//CR: TODO: Implement this
	throw new Error("Not Implemented");
}

/**
 * Checks if this entity value is resolved.
 * 
 * @return <code>true</code> if the entity is resolved;
 * 		<code>false</code> otherwise.
 */
public boolean isResolved() {
	return resolved;
}
/**
 * Parses the entity value from the string.
 * 
 * @return The entity value.
 * 
 * @param dtdFrag The dtd stream.
 */
private String readEntityValue(DTDData dtdFrag) {

	char delim = dtdFrag.lookNextChar();
	if( (delim == '\'') || (delim == '\"') ) { //EntityValue
		char[] paramDefDelim = { dtdFrag.getNextChar() }; // this should be either ' or "
		
		String entityVal = dtdFrag.getNextToken( paramDefDelim );
		return entityVal;
	}

	return null;
}
/**
 * Insert the method's description here.
 * @return java.lang.String
 * @param dtdFrag com.conradroche.matra.decl.Data
 */
private String readExtID(DTDData dtdFrag) throws DTDException {

/*
[75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral

[11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
[12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
[13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
*/
	char delim;
	
	String identifier = dtdFrag.getNextToken();
	if( identifier.equals("SYSTEM") ) {
		setExternalIDType(Entity.EXT_ID_SYSTEM);
		dtdFrag.skipWhiteSpace();//S
		//SystemLiteral
		delim = dtdFrag.lookNextChar(); //this has to be ' or "
		if( (delim != '\'') && (delim != '\"') ) {
			throw new DTDException("Invalid character (" + delim + ") encountered at location " + dtdFrag.getCurrentLocation() + " - was expecting '\'' or '\"'.");
		}
		char[] sysLiteralDelim = { dtdFrag.getNextChar() }; // this should be either ' or "
		String SystemLiteral = dtdFrag.getNextToken( sysLiteralDelim );
		setSystemLiteral(SystemLiteral);
	}
	else if( identifier.equals("PUBLIC") ) {
		setExternalIDType(Entity.EXT_ID_PUBLIC);
		dtdFrag.skipWhiteSpace();
		//PubidLiteral
		delim = dtdFrag.lookNextChar(); //this has to be ' or "
		if( (delim != '\'') && (delim != '\"') ) {
			throw new DTDException("Invalid character (" + delim + ") encountered at location " + dtdFrag.getCurrentLocation() + " - was expecting '\'' or '\"'.");
		}
		char[] pubidLiteralDelim = { dtdFrag.getNextChar() }; // this should be either ' or "
		String PubidLiteral = dtdFrag.getNextToken( pubidLiteralDelim );
		setPubidLiteral(PubidLiteral);

		dtdFrag.skipWhiteSpace();//S
		//SystemLiteral
		delim = dtdFrag.lookNextChar(); //this has to be ' or "
		if( (delim != '\'') && (delim != '\"') ) {
			throw new DTDException("Invalid character (" + delim + ") encountered at location " + dtdFrag.getCurrentLocation() + " - was expecting '\'' or '\"'.");
		}
		char[] sysLiteralDelim = { dtdFrag.getNextChar() }; // this should be either ' or "
		String SystemLiteral = dtdFrag.getNextToken( sysLiteralDelim );
		setSystemLiteral(SystemLiteral);
	}
	else {
		//debug
		System.out.println(dtdFrag.toString());
		throw new DTDException("Invalid identifier (" + identifier + ") specified - only \"PUBLIC\" or \"SYSTEM\" can be specified.");
	}
	return null;
}
/**
 * Insert the method's description here.
 */
private void reset() {

	externalIDType = EXT_ID_NONE;	
}
/**
 * Insert the method's description here.
 * @return com.conradroche.matra.decl.Data
 * @param unresolvedDTD com.conradroche.matra.decl.Data
 */
private DTDData resolveEntities(DTDData content, Hashtable EntityList) {

	String newContent = "";
	char[] entityDelim = { '&', '%' };
	
	newContent += content.getNextToken( entityDelim );
	
	while( !content.endOfData() ) {
		boolean pEntity = (content.getPrevChar() == '%' ? true : false);
		
		String entName = content.getNextToken(';');
		Entity entity = (Entity) EntityList.get( entName );
		
		if( entity == null ) {
			if(entName.charAt(0) == '#') { //CharRef
				int index = 10;
				
				if(entName.charAt(2) == 'x') { //hex char
					index = 16;
				}
				String charValue = entName.substring(2, entName.length());
				char ch = (char) Integer.parseInt(charValue, index);

				newContent += ch;
			}
			else
				newContent += (pEntity ? '%' : '&') + entName + ';';
		}
		else {
			String entValue = entity.getLiteralValue();
			newContent += entValue;
		}
		newContent += content.getNextToken( entityDelim );
	}

	return new DTDData(newContent);
}
/**
 * Insert the method's description here.
 * 
 * @param entityList The master list of all entities.
 * 
 * @throws DTDException 
 */
public void resolveValue(Hashtable entityList) throws DTDException {

/*
[9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' | "'" ([^%&'] | PEReference | Reference)* "'"

[69] PEReference ::= '%' Name ';' 
[67] Reference ::= EntityRef | CharRef

[68] EntityRef ::= '&' Name ';' 
[66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';' 
*/
	DTDData entValue = new DTDData(literalValue);

	literalValue = "";
	hasEntityRef = false;
	resolved = true;

	while( !entValue.endOfData() ) {
		String token = entValue.getNextToken( '&' );
		literalValue += token;

		if(entValue.lookNextChar() == '#') { //CharRef
			int index = 10;
			
			entValue.getNextChar(); //'#'
			if(entValue.lookNextChar() == 'x') { //hex char
				entValue.getNextChar(); //'x'
				index = 16;
			}
			String charValue = entValue.getNextToken( ';' );
			char ch = (char) Integer.parseInt(charValue, index);

			literalValue += ch;
		}
		else { //EntityRef
			String entRefName = entValue.getNextToken( ';' );

			Entity ent = (Entity) entityList.get(entRefName);
			if(ent == null)
				throw new DTDException("Entity, " +  getEntityName() + ", referes to an undefined entity - " + entRefName);
			if( !ent.isResolved() ) {
				literalValue += '&' + entRefName + ';';
				resolved = false;
			}
			else
				literalValue += ent.getLiteralValue();
		}
	}
}
/**
 * Sets the external ID type for this entity.
 * 
 * @see #getExternalIDType
 * 
 * @param newExternalIDType The external ID type for this entity.
 */
private void setExternalIDType(int newExternalIDType) {
	externalIDType = newExternalIDType;
}

/**
 * Sets the Entity Name.
 * 
 * @param newName the Entity Name.
 * 
 * @see #getEntityName
 */
public void setEntityName(String newName) {
	name = newName;
}
/**
 * Sets the public identifier for this entity.
 * 
 * @param newPubidLiteral the public identifier for this entity.
 */
private void setPubidLiteral(java.lang.String newPubidLiteral) {
	pubidLiteral = newPubidLiteral;
}
/**
 * Insert the method's description here.
 * @param newResolved boolean
 */
private void setResolved(boolean newResolved) {
	resolved = newResolved;
}
/**
 * Insert the method's description here.
 * @param newSystemLiteral java.lang.String
 */
private void setSystemLiteral(java.lang.String newSystemLiteral) {
	systemLiteral = newSystemLiteral;
}
/**
 * Sets the entity type.
 * 
 * @param newType the entity type.
 * 
 * @see #getType
 */
public void setType(int newType) {
	type = newType;
}
/**
 * Sets the literal value of this entity.
 * 
 * @param newValue The literal value of this entity.
 * 
 * @see #getLiteralValue
 */
public void setLiteralValue(String newValue) {

	literalValue = newValue;
	resolved = false;
}
/**
 * Returns a DTD String representation for this entity.
 * 
 * @return The DTD string representation.
 */
public String toString() {
/*
[70] EntityDecl ::= GEDecl | PEDecl
[71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
[72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'

[73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
[74] PEDef ::= EntityValue | ExternalID

[9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' | "'" ([^%&'] | PEReference | Reference)* "'"
[75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral
[76] NDataDecl ::= S 'NDATA' S Name

[11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
[12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
[13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
*/

	String entityDecl;

	entityDecl = "<!ENTITY "; //'<!ENTITY' S

	if(getType() == PARAMETER_ENTITY)
		entityDecl += "% "; //'%' S

	entityDecl += getEntityName() + " "; //Name S

	int extIDType = getExternalIDType();
	
	if(extIDType == EXT_ID_NONE) { //EntityValue
		entityDecl += "\"" + getLiteralValue() + "\"";
	}
	else if(extIDType == EXT_ID_SYSTEM) {
		entityDecl += "SYSTEM " + getSystemIdentifier(); //'SYSTEM' S SystemLiteral
	}
	else if(extIDType == EXT_ID_PUBLIC) {
		entityDecl += "PUBLIC " + getPublicIdentifier() + " " + getSystemIdentifier(); //'PUBLIC' S PubidLiteral S SystemLiteral
	}

	entityDecl += ">"; //'>'
		
	return entityDecl;
}

/**
 * Returns <code>true</code> if the Entity is
 * a General Entity and <code>false</code> otherwise.
 * 
 * @return <code>true</code> for General Entity
 * 		and <code>false</code> otherwise.
 * 
 * @see com.conradroche.dtd.decl.Entity#isGeneralEntity()
 */
public boolean isGeneralEntity() {
	//CR: TODO: Implement this
	throw new Error("Not Implemented");
}

/**
 * Returns <code>true</code> if the Entity is
 * a Parameter Entity and <code>false</code> otherwise.
 * 
 * @return <code>true</code> for Parameter Entity
 * 		and <code>false</code> otherwise.
 * 
 * @see com.conradroche.dtd.decl.Entity#isParameterEntity()
 */
public boolean isParameterEntity() {
	//CR: TODO: Implement this
	throw new Error("Not Implemented");
}

/**
 * Returns <code>true</code> if the 
 * System Identifier is specified.
 * 
 * @return <code>true</code> if the 
 * 		System Identifier is specified
 * 		<code>false</code> otherwise.
 * 
 * @see com.conradroche.dtd.decl.ExternalID#hasSystemIdentifier()
 */
public boolean hasSystemIdentifier() {
	//CR: TODO: Implement this
	throw new Error("Not Implemented");
}

/**
 * Returns <code>true</code> if the 
 * Public Identifier is specified.
 * 
 * @return <code>true</code> if the 
 * 		Public Identifier is specified
 * 		<code>false</code> otherwise.
 * 
 * @see com.conradroche.dtd.decl.ExternalID#hasPublicIdentifier()
 */
public boolean hasPublicIdentifier() {
	//CR: TODO: Implement this
	throw new Error("Not Implemented");
}
}

